package com.xiyun.f1101t1200;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Semaphore;

public class GenerateH2O_1117 {
    public static void resolve(String[] args) throws InterruptedException {
        String water = "OOHHHHOHH";
        GenerateH2O_1117.H2O h2O = new GenerateH2O_1117().new H2O();
        StringBuffer buffer = new StringBuffer();
        char[] chars = water.toCharArray();
        CountDownLatch latch = new CountDownLatch(chars.length);
        for (char c : chars) {
            if ('H' == c) {
                new Thread(()->{
                    try {
                        h2O.hydrogen(()-> buffer.append('H'));
                        latch.countDown();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }).start();
            } else {
                new Thread(()->{
                    try {
                        h2O.oxygen(()-> buffer.append('O'));
                        latch.countDown();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }).start();
            }
        }
        latch.await();
        System.out.println(buffer);
    }
    class H2O {
        Semaphore o = new Semaphore(1);
        Semaphore h = new Semaphore(2);
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
        public H2O() {

        }

        public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
            h.acquire();
            try {
                cyclicBarrier.await();
            } catch (BrokenBarrierException e) {
                throw new RuntimeException(e);
            }
            // releaseHydrogen.run() outputs "H". Do not change or remove this line.
            releaseHydrogen.run();
            h.release();
        }

        public void oxygen(Runnable releaseOxygen) throws InterruptedException {
            o.acquire();
            try {
                cyclicBarrier.await();
            } catch (BrokenBarrierException e) {
                throw new RuntimeException(e);
            }
            // releaseOxygen.run() outputs "O". Do not change or remove this line.
            releaseOxygen.run();
            o.release();
        }
    }
}
